package com.fangcun.common.util.file;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletResponse;

import org.springframework.util.FileCopyUtils;

/**
 * @作者： 陳曉鬆 @时间： 2018年3月28日 - 上午10:55:48 @description：->
 */
public class FileUtils {

	/**
	 * 
	 * @description：-> 删除文件
	 * 
	 * @param path
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2018年3月28日 上午10:57:26 @版本：V1.0
	 *
	 */
	public static boolean deleteFile(String path) {
		File file = new File(path);
		if (file.exists()) {
			return file.delete();
		} else {
			return false;
		}
	}

	/**
	 * 迭代删除文件夹
	 * 
	 * @param dirPath
	 *            文件夹路径
	 */
	public static void deleteDir(String dirPath) {
		File file = new File(dirPath);
		if (file.isFile()) {
			file.delete();
		} else {
			File[] files = file.listFiles();
			if (files == null) {
				file.delete();
			} else {
				for (int i = 0; i < files.length; i++) {
					deleteDir(files[i].getAbsolutePath());
				}
				file.delete();
			}
		}
	}

	/**
	 * 使用FileWriter类写文本文件
	 */
	public static void writeMethod(String fileName, String content) {
		try {
			// 使用这个构造函数时，如果存在kuka.txt文件，
			// 则先把这个文件给删除掉，然后创建新的kuka.txt
			FileWriter writer = new FileWriter(fileName);
			writer.write(content);
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @description：-> 获取文件列表
	 * 
	 * @param basePath
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2019年3月15日 下午2:04:53 @版本：V1.0
	 *
	 */
	public static File[] getFileList(String basePath) {
		try {
			File file = new File(basePath);// File类型可以是文件也可以是文件夹
			File[] fileList = file.listFiles();// 将该目录下的所有文件放置在一个File类型的数组中
			return fileList;
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 从输入流中获取字节数组
	 * 
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	public static byte[] readInputStream(InputStream inputStream) throws IOException {
		byte[] buffer = new byte[1024];
		int len = 0;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		while ((len = inputStream.read(buffer)) != -1) {
			bos.write(buffer, 0, len);
		}
		bos.close();
		return bos.toByteArray();
	}

	/**
	 * 下载文件
	 * 
	 * @param url
	 *            文件地址
	 * @param dir
	 *            存储目录
	 * @param fileName
	 *            存储文件名
	 * @return
	 */
	public static Boolean downloadHttpUrl(String url, String dir, String fileName) {
		try {
			URL httpurl = new URL(url);
			File dirfile = new File(dir);
			if (!dirfile.exists()) {
				dirfile.mkdirs();
			}
			HttpURLConnection conn = (HttpURLConnection) httpurl.openConnection();
			// 设置超时间为10秒
			conn.setConnectTimeout(10 * 1000);
			// 防止屏蔽程序抓取而返回403错误
			conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
			FileCopyUtils.copy(readInputStream(conn.getInputStream()), new File(dir + fileName));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return true;
	}

	/**
	 * 
	 * @description：-> zip解压缩
	 * 
	 * @param zipPath
	 *            zip文件路径
	 * @param descDir
	 *            解压过后路径
	 * @throws IOException
	 *
	 * @作者：陳曉鬆
	 * @时间：2020年1月6日 上午11:27:09 @版本：V1.0
	 *
	 */
	public static Boolean unZipFiles(String zipPath, String descDir) {
		System.out.println("文件:" + zipPath + ". 解压路径:" + descDir + ". 解压开始.");
		long start = System.currentTimeMillis();
		try {
			File zipFile = new File(zipPath);
			if (!zipFile.exists()) {
				throw new IOException("需解压文件不存在.");
			}
			File pathFile = new File(descDir);
			if (!pathFile.exists()) {
				pathFile.mkdirs();
			}
			ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));
			for (Enumeration<?> entries = zip.entries(); entries.hasMoreElements();) {
				ZipEntry entry = (ZipEntry) entries.nextElement();
				String zipEntryName = entry.getName();
				InputStream in = zip.getInputStream(entry);
				String outPath = (descDir + File.separator + zipEntryName).replaceAll("\\*", "/");
				// 判断路径是否存在,不存在则创建文件路径
				File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
				if (!file.exists()) {
					file.mkdirs();
				}
				// 判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
				if (new File(outPath).isDirectory()) {
					continue;
				}
				// 输出文件路径信息
				OutputStream out = new FileOutputStream(outPath);
				byte[] buf1 = new byte[1024];
				int len;
				while ((len = in.read(buf1)) > 0) {
					out.write(buf1, 0, len);
				}
				in.close();
				out.close();
			}
			zip.close();
			System.out.println("文件:" + zipPath + ". 解压路径:" + descDir + ". 解压完成. 耗时:" + (System.currentTimeMillis() - start) + "ms. ");
		} catch (Exception e) {
			System.out.println("文件:" + zipPath + ". 解压路径:" + descDir + ". 解压异常. 耗时:" + (System.currentTimeMillis() - start) + "ms. ");
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 
	 * @description：-> 读取文件内容
	 * 
	 * @param file
	 * @return
	 *
	 * @作者：陳曉鬆
	 * @时间：2020年1月6日 下午5:37:09 @版本：V1.0
	 *
	 */
	public static String readTxtString(File file) {
		try {
			BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file));
			@SuppressWarnings("resource")
			BufferedReader reader = new BufferedReader(new InputStreamReader(fis, "utf-8"), 5 * 1024 * 1024);// 用5M的缓冲读取文本文件
			StringBuffer sb = new StringBuffer();
			String line = "";
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			return sb.toString();
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 压缩成ZIP 方法
	 * 
	 * @param sourceFile
	 *            压缩文件夹路径
	 * @param zipFilePath
	 *            压缩文件zip路径
	 * @param fileName
	 *            文件名称
	 * @param KeepDirStructure
	 *            是否保留原来的目录结构,true:保留目录结构; false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
	 * @throws RuntimeException
	 *             压缩失败会抛出运行时异常
	 */
	public static void toZip(String sourceFile, String zipFilePath, String fileName, boolean KeepDirStructure) throws RuntimeException {
		ZipOutputStream zos = null;
		try {
			zos = new ZipOutputStream(new FileOutputStream(new File(zipFilePath + fileName + ".zip")));
			File sourceFilePath = new File(sourceFile);
			compress(sourceFilePath, zos, sourceFilePath.getName(), KeepDirStructure);
		} catch (Exception e) {
			throw new RuntimeException("zip error from ZipUtils", e);
		} finally {
			if (zos != null) {
				try {
					zos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 递归压缩方法
	 * 
	 * @param sourceFile
	 *            源文件
	 * @param zos
	 *            zip输出流
	 * @param name
	 *            压缩后的名称
	 * @param KeepDirStructure
	 *            是否保留原来的目录结构,true:保留目录结构; false:所有文件跑到压缩包根目录下(注意：不保留目录结构可能会出现同名文件,会压缩失败)
	 * @throws Exception
	 */
	private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean KeepDirStructure) throws Exception {
		byte[] buf = new byte[2 * 1024];
		if (sourceFile.isFile()) {
			// 向zip输出流中添加一个zip实体，构造器中name为zip实体的文件的名字
			zos.putNextEntry(new ZipEntry(name));
			// copy文件到zip输出流中
			int len;
			FileInputStream in = new FileInputStream(sourceFile);
			while ((len = in.read(buf)) != -1) {
				zos.write(buf, 0, len);
			}
			// Complete the entry
			zos.closeEntry();
			in.close();
		} else {
			File[] listFiles = sourceFile.listFiles();
			if (listFiles == null || listFiles.length == 0) {
				// 需要保留原来的文件结构时,需要对空文件夹进行处理
				if (KeepDirStructure) {
					// 空文件夹的处理
					zos.putNextEntry(new ZipEntry(name + "/"));
					// 没有文件，不需要文件的copy
					zos.closeEntry();
				}
			} else {
				for (File file : listFiles) {
					// 判断是否需要保留原来的文件结构
					if (KeepDirStructure) {
						// 注意：file.getName()前面需要带上父文件夹的名字加一斜杠,
						// 不然最后压缩包中就不能保留原来的文件结构,即：所有文件都跑到压缩包根目录下了
						compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
					} else {
						compress(file, zos, file.getName(), KeepDirStructure);
					}
				}
			}
		}
	}

	/**
	 * @作者：陳曉鬆 @时间：2020年7月3日 下午5:43:07 @版本：V1.0 @description：-> 下载文件
	 */
	public static void download(String filePath, HttpServletResponse res) {
		// 发送给客户端的数据
		OutputStream outputStream = null;
		BufferedInputStream bis = null;
		try {
			outputStream = res.getOutputStream();
			byte[] buff = new byte[1024];
			// 读取filePath
			bis = new BufferedInputStream(new FileInputStream(new File(filePath)));
			int i = bis.read(buff);
			while (i != -1) {
				outputStream.write(buff, 0, buff.length);
				outputStream.flush();
				i = bis.read(buff);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				bis.close();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main1(String[] args) {
		toZip("D:\\botany\\images\\1", "C:\\Users\\Administrator\\Desktop\\", "11", true);
	}

}